﻿using System.Windows;
using Prism.Events;
using Prism.Ioc;
using System.Windows.Controls;
using Module.CanJuSheJi.Common;
using System.Diagnostics;

namespace Module.CanJuSheJi.Views
{
    /// <summary>
    /// Interaction logic for CanJuPoJie
    /// </summary>
    public partial class ChessBoard : UserControl
    {
        private readonly IEventAggregator Ea;
        public string ModuleName { get; set; } // 模块名称，用于订阅消息过滤。很关键。
        public string ClassName { get; set; } // 类名称，用于跟踪订阅消息发出者。主要用于调试，对软件无实质作用。
        private bool SideTag;

        public ChessPieces[] PiecessArray = new ChessPieces[32]; // 棋子数组，所有棋子均在此数组中
        public MovePoint[,] MovePointArray = new MovePoint[9, 10]; // 可移动点实例数组。可移动点实例的作用，一是在棋盘上显示当前选中棋子可到达的位置，二是接收鼠标点击事件，发出点击位置信息，棋子接收后，移动到该位置。
        public int[,] ChessBoardData = new int[9, 12]; // 棋盘数据信息，记录整个棋盘上的棋子所在位置。为-1时，表示该位置没有棋子，为0-31时，表示该位置有棋子，数字是棋子的编号。
        public string BoardDataFenStr;

        public ChessBoard(IEventAggregator ea, IContainerProvider Cp, string moduleName)
        {
            InitializeComponent();
            this.Ea = ea;
            ModuleName = moduleName;
            ClassName = this.GetType().Name;
            Ea.GetEvent<CanJuSheJiMessageEvent>().Subscribe(ModuleMessageProcess, ThreadOption.PublisherThread, false, filter => filter.ModuleName.Equals(ModuleName));


            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 10; j++)
                {
                    MovePointArray[i, j] = Cp.Resolve<MovePoint>(); // 棋盘上添加可移动点
                    MovePointArray[i, j].SetInitPosition(i, j);
                    movePointGrid.Children.Add(MovePointArray[i, j]);
                    MovePointArray[i, j].ModuleName = ModuleName;
                }
            for (int i = 0; i < 32; i++)
            {
                PiecessArray[i] = Cp.Resolve<ChessPieces>();// 棋盘上添加棋子
                PiecessArray[i].SetID(i); // 设置棋子编号
                qiZiGrid.Children.Add(PiecessArray[i]);
                PiecessArray[i].SetDefaultInitPosition(); // 棋子放置到初始位置
                PiecessArray[i].ModuleName = ModuleName;
            }

            SideTag = GlobalData.REDSIDE;
        }
        #region 订阅消息处理
        /// <summary>
        /// 模块消息处理
        /// </summary>
        /// <param name="obj">消息体</param>
        public void ModuleMessageProcess(CanJuSheJiMessage obj)
        {
            switch (obj.MessageName)
            {
                case "qiziLocationHasChanged":
                    // 吃子处理
                    QiPanDataRefresh();
                    int dieQz = ChessBoardData[obj.NewCol, obj.NewRow];
                    if (obj.NewRow<10 && dieQz >= 0)
                    {
                        PiecessArray[dieQz].Visibility = System.Windows.Visibility.Hidden; // 吃子
                    }
                    PiecessArray[obj.Id].CurCol = obj.NewCol;
                    PiecessArray[obj.Id].CurRow = obj.NewRow;
                    
                    
                    BoardDataFenStr = QiPanDataToFenStr_MainBody();
                    Debug.Print($"FEMstr = { BoardDataFenStr }");
                    break;
                default: break;
            }
        }

        #endregion

        /// <summary>
        /// 棋盘数据更新
        /// </summary>
        public void QiPanDataRefresh()
        {
            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 12; j++)
                {
                    ChessBoardData[i, j] = -1;
                }
            for (int i = 0; i < 32; i++)
            {
                if (PiecessArray[i].IsVisible) ChessBoardData[PiecessArray[i].CurCol, PiecessArray[i].CurRow] = i; // 获取棋盘数据
            }
        }

        /// <summary>
        /// 设置棋子到默认位置
        /// </summary>
        public void SetPieceOnDefaultInitPosition()
        {
            for (int i = 0; i < 32; i++)
            {
                PiecessArray[i].SetDefaultInitPosition();
            }
            SideTag = GlobalData.REDSIDE;
        }

        /// <summary>
        /// 依据给定的棋盘局面数据，设置棋子到指定位置
        /// </summary>
        /// <param name="FenString">Fen格式棋盘局面数据</param>
        public void SetPieceOnAssignInitPosition(string FenString)
        {
            int[,] QiPanData = GlobalFunction.ConvertFenStrToQiPan(FenString);
            for (int i = 0; i < 32; i++)
            {
                PiecessArray[i].Visibility = Visibility.Hidden;
                PiecessArray[i].SetAssignInitPosition(-1, -1);
            }
            for (int i = 0; i <= 8; i++)
            {
                for (int j = 0; j <= 9; j++)
                {
                    int qizi = QiPanData[i, j];
                    if (qizi > -1)
                    {
                        PiecessArray[qizi].SetAssignInitPosition(i, j);
                    }
                }
            }
            SideTag = GlobalData.REDSIDE;
        }

        // UCCI标准棋子名称，小写为黑方，对应0-15，大写为红方，对应16-31
        private static readonly string[] Fen = {
            "k","a","a","b","b","n","n","r","r","c","c","p","p","p","p","p",
            "K","A","A","B","B","N","N","R","R","C","C","P","P","P","P","P"
        };

        /// <summary>
        /// 棋盘数据转换为FEN格式字符串，用于保存到数据库中。
        /// </summary>
        /// <returns></returns>
        public string QiPanDataToFenStr_MainBody()
        {
            #region 棋盘数据生成FEN字符串
            string output = "";
            QiPanDataRefresh();
            for (int i = 0; i < 10; i++) // 行
            {
                string lineString = "";
                int spaceNum = 0;
                for (int j = 0; j < 9; j++) // 列
                {
                    int qz = ChessBoardData[j, i];
                    if (qz == -1)
                    {
                        spaceNum++;
                    }
                    if (qz > -1)
                    {
                        if (spaceNum > 0)
                        {
                            lineString += spaceNum.ToString();
                            spaceNum = 0;
                        }
                        lineString += Fen[qz];
                    }
                }
                if (spaceNum > 0)
                {
                    lineString += spaceNum.ToString();
                }
                output += lineString;
                if (i < 9)
                {
                    output += "/";
                }
            }
            return output;
            #endregion
        }

    }
}
